﻿namespace Fiddler
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;

    internal class HTTPSClientHello
    {
        private uint[] _CipherSuites;
        private byte[] _CompressionSuites;
        private List<string> _Extensions;
        private int _HandshakeVersion;
        private int _MajorVersion;
        private int _MessageLen;
        private int _MinorVersion;
        private byte[] _Random;
        private string _ServerNameIndicator;
        private byte[] _SessionID;
        internal static readonly Dictionary<uint, string> dictTLSCipherSuites;
        internal static readonly string[] HTTPSCompressionSuites = new string[] { "NO_COMPRESSION", "DEFLATE" };
        internal static readonly string[] SSL3CipherSuites = new string[] { 
            "SSL_NULL_WITH_NULL_NULL", "SSL_RSA_WITH_NULL_MD5", "SSL_RSA_WITH_NULL_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_EXPORT_WITH_RC2_40_MD5", "SSL_RSA_WITH_IDEA_SHA", "SSL_RSA_EXPORT_WITH_DES40_SHA", "SSL_RSA_WITH_DES_SHA", "SSL_RSA_WITH_3DES_EDE_SHA", "SSL_DH_DSS_EXPORT_WITH_DES40_SHA", "SSL_DH_DSS_WITH_DES_SHA", "SSL_DH_DSS_WITH_3DES_EDE_SHA", "SSL_DH_RSA_EXPORT_WITH_DES40_SHA", "SSL_DH_RSA_WITH_DES_SHA", 
            "SSL_DH_RSA_WITH_3DES_EDE_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_SHA", "SSL_DHE_DSS_WITH_DES_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_SHA", "SSL_DHE_RSA_WITH_DES_SHA", "SSL_DHE_RSA_WITH_3DES_EDE_SHA", "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "SSL_DH_anon_WITH_RC4_128_MD5", "SSL_DH_anon_EXPORT_WITH_DES40_SHA", "SSL_DH_anon_WITH_DES_SHA", "SSL_DH_anon_WITH_3DES_EDE_SHA", "SSL_FORTEZZA_KEA_WITH_NULL_SHA", "SSL_FORTEZZA_KEA_WITH_FORTEZZA_SHA", "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"
         };

        static HTTPSClientHello()
        {
            Dictionary<uint, string> dictionary = new Dictionary<uint, string>();
            dictionary.Add(30, "TLS_KRB5_WITH_DES_SHA");
            dictionary.Add(0x1f, "TLS_KRB5_WITH_3DES_EDE_SHA");
            dictionary.Add(0x20, "TLS_KRB5_WITH_RC4_128_SHA");
            dictionary.Add(0x21, "TLS_KRB5_WITH_IDEA_SHA");
            dictionary.Add(0x22, "TLS_KRB5_WITH_DES_MD5");
            dictionary.Add(0x23, "TLS_KRB5_WITH_3DES_EDE_MD5");
            dictionary.Add(0x24, "TLS_KRB5_WITH_RC4_128_MD5");
            dictionary.Add(0x25, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA");
            dictionary.Add(0x26, "TLS_KRB5_EXPORT_WITH_DES_40_SHA");
            dictionary.Add(0x27, "TLS_KRB5_EXPORT_WITH_RC2_40_SHA");
            dictionary.Add(40, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA");
            dictionary.Add(0x29, "TLS_KRB5_EXPORT_WITH_DES_40_MD5");
            dictionary.Add(0x2a, "TLS_KRB5_EXPORT_WITH_RC2_40_MD5");
            dictionary.Add(0x2b, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5");
            dictionary.Add(0x2f, "TLS_RSA_AES_128_SHA");
            dictionary.Add(0x30, "TLS_DH_DSS_WITH_AES_128_SHA");
            dictionary.Add(0x31, "TLS_DH_RSA_WITH_AES_128_SHA");
            dictionary.Add(50, "TLS_DHE_DSS_WITH_AES_128_SHA");
            dictionary.Add(0x33, "TLS_DHE_RSA_WITH_AES_128_SHA");
            dictionary.Add(0x34, "TLS_DH_ANON_WITH_AES_128_SHA");
            dictionary.Add(0x35, "TLS_RSA_AES_256_SHA");
            dictionary.Add(0x36, "TLS_DH_DSS_WITH_AES_256_SHA");
            dictionary.Add(0x37, "TLS_DH_RSA_WITH_AES_256_SHA");
            dictionary.Add(0x38, "TLS_DHE_DSS_WITH_AES_256_SHA");
            dictionary.Add(0x39, "TLS_DHE_RSA_WITH_AES_256_SHA");
            dictionary.Add(0x3a, "TLS_DH_ANON_WITH_AES_256_SHA");
            dictionary.Add(0x3e, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0x3f, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0x41, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA");
            dictionary.Add(0x44, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA");
            dictionary.Add(0x45, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA");
            dictionary.Add(0x47, "TLS_ECDH_ECDSA_WITH_NULL_SHA");
            dictionary.Add(0x48, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
            dictionary.Add(0x49, "TLS_ECDH_ECDSA_WITH_DES_SHA");
            dictionary.Add(0x4a, "TLS_ECDH_ECDSA_WITH_3DES_EDE_SHA");
            dictionary.Add(0x4b, "TLS_ECDH_ECDSA_WITH_AES_128_SHA");
            dictionary.Add(0x4c, "TLS_ECDH_ECDSA_WITH_AES_256_SHA");
            dictionary.Add(0x4d, "TLS_ECDH_RSA_WITH_NULL_SHA");
            dictionary.Add(0x4e, "TLS_ECDH_RSA_WITH_RC4_128_SHA");
            dictionary.Add(0x4f, "TLS_ECDH_RSA_WITH_DES_SHA");
            dictionary.Add(80, "TLS_ECDH_RSA_WITH_3DES_EDE_SHA");
            dictionary.Add(0x51, "TLS_ECDH_RSA_WITH_AES_128_SHA");
            dictionary.Add(0x52, "TLS_ECDH_RSA_WITH_AES_256_SHA");
            dictionary.Add(0x62, "TLS_RSA_EXPORT1024_WITH_DES_SHA");
            dictionary.Add(0x63, "TLS_DHE_DSS_EXPORT1024_WITH_DES_SHA");
            dictionary.Add(100, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA");
            dictionary.Add(0x65, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA");
            dictionary.Add(0x66, "TLS_DHE_DSS_WITH_RC4_128_SHA");
            dictionary.Add(0x67, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0x68, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256");
            dictionary.Add(0x69, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256");
            dictionary.Add(0x6b, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256");
            dictionary.Add(0x77, "TLS_ECDHE_ECDSA_WITH_AES_128_SHA");
            dictionary.Add(120, "TLS_ECDHE_RSA_WITH_AES_128_SHA");
            dictionary.Add(0x84, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA");
            dictionary.Add(0x87, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA");
            dictionary.Add(0x88, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA");
            dictionary.Add(150, "TLS_RSA_WITH_SEED_CBC_SHA");
            dictionary.Add(0xff, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
            dictionary.Add(0xc002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
            dictionary.Add(0xc003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
            dictionary.Add(0xc004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
            dictionary.Add(0xc005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
            dictionary.Add(0xc007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
            dictionary.Add(0xc008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
            dictionary.Add(0xc00c, "TLS_ECDH_RSA_WITH_RC4_128_SHA");
            dictionary.Add(0xc00d, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
            dictionary.Add(0xc00e, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
            dictionary.Add(0xc00f, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
            dictionary.Add(0xc011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
            dictionary.Add(0xc012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
            dictionary.Add(0xc009, "TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
            dictionary.Add(0xc00a, "TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
            dictionary.Add(0xc013, "TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA");
            dictionary.Add(0xc014, "TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA");
            dictionary.Add(60, "TLS_RSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0x3d, "TLS_RSA_WITH_AES_256_CBC_SHA256");
            dictionary.Add(0x40, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0x6a, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
            dictionary.Add(0xc023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0xc024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
            dictionary.Add(0xc027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0xc028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
            dictionary.Add(0xc02b, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
            dictionary.Add(0xc02c, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
            dictionary.Add(0x3b, "TLS_RSA_WITH_NULL_SHA256");
            dictionary.Add(0xc001, "TLS_ECDH_ECDSA_WITH_NULL_SHA");
            dictionary.Add(0xc006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA");
            dictionary.Add(0xc00b, "TLS_ECDH_RSA_WITH_NULL_SHA");
            dictionary.Add(0xc010, "TLS_ECDHE_RSA_WITH_NULL_SHA");
            dictionary.Add(0xc025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0xc026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384");
            dictionary.Add(0xc029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256");
            dictionary.Add(0xc02a, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384");
            dictionary.Add(0xff01, "SSL_EN_RC4_128_WITH_MD5");
            dictionary.Add(0xff02, "SSL_EN_RC4_128_EXPORT40_WITH_MD5");
            dictionary.Add(0xff03, "SSL_EN_RC2_128_WITH_MD5");
            dictionary.Add(0xff04, "SSL_EN_RC2_128_EXPORT40_WITH_MD5");
            dictionary.Add(0xff05, "SSL_EN_IDEA_128_WITH_MD5");
            dictionary.Add(0xff06, "SSL_EN_DES_64_WITH_MD5");
            dictionary.Add(0xff07, "SSL_EN_DES_192_EDE3_WITH_MD5");
            dictionary.Add(0xfeff, "SSL_RSA_FIPS_WITH_3DES_EDE_SHA");
            dictionary.Add(0xfefe, "SSL_RSA_FIPS_WITH_DES_SHA");
            dictionary.Add(0xffe0, "SSL_RSA_NSFIPS_WITH_3DES_EDE_SHA");
            dictionary.Add(0xffe1, "SSL_RSA_NSFIPS_WITH_DES_SHA");
            dictionary.Add(0x10080, "SSL2_RC4_128_WITH_MD5");
            dictionary.Add(0x20080, "SSL2_RC4_128_EXPORT40_WITH_MD5");
            dictionary.Add(0x30080, "SSL2_RC2_128_WITH_MD5");
            dictionary.Add(0x40080, "SSL2_RC2_128_EXPORT40_WITH_MD5");
            dictionary.Add(0x50080, "SSL2_IDEA_128_WITH_MD5");
            dictionary.Add(0x60040, "SSL2_DES_64_WITH_MD5");
            dictionary.Add(0x700c0, "SSL2_DES_192_EDE3_WITH_MD5");
            dictTLSCipherSuites = dictionary;
        }

        private static string CipherSuitesToString(uint[] inArr)
        {
            if (inArr == null)
            {
                return "null";
            }
            if (inArr.Length == 0)
            {
                return "empty";
            }
            StringBuilder builder = new StringBuilder(inArr.Length * 20);
            for (int i = 0; i < inArr.Length; i++)
            {
                builder.Append("\t[" + inArr[i].ToString("X4") + "]\t");
                if (inArr[i] < SSL3CipherSuites.Length)
                {
                    builder.AppendLine(SSL3CipherSuites[inArr[i]]);
                }
                else if (dictTLSCipherSuites.ContainsKey(inArr[i]))
                {
                    builder.AppendLine(dictTLSCipherSuites[inArr[i]]);
                }
                else
                {
                    builder.AppendLine("Unrecognized cipher - See http://www.iana.org/assignments/tls-parameters/");
                }
            }
            return builder.ToString();
        }

        private static string CompressionSuitesToString(byte[] inArr)
        {
            if (inArr == null)
            {
                return "(not specified)";
            }
            if (inArr.Length == 0)
            {
                return "(none)";
            }
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < inArr.Length; i++)
            {
                builder.Append("\t[" + inArr[i].ToString("X2") + "]\t");
                if (inArr[i] < HTTPSCompressionSuites.Length)
                {
                    builder.AppendLine(HTTPSCompressionSuites[inArr[i]]);
                }
                else
                {
                    builder.AppendLine("Unrecognized compression format");
                }
            }
            return builder.ToString();
        }

        private static string ExtensionListToString(List<string> slExts)
        {
            if ((slExts != null) && (slExts.Count >= 1))
            {
                return string.Join("\n", slExts.ToArray());
            }
            return "\tnone";
        }

        internal bool LoadFromStream(Stream oNS)
        {
            int num = 0;
            switch (oNS.ReadByte())
            {
                case 0x80:
                {
                    this._HandshakeVersion = 2;
                    oNS.ReadByte();
                    oNS.ReadByte();
                    this._MajorVersion = oNS.ReadByte();
                    this._MinorVersion = oNS.ReadByte();
                    if ((this._MajorVersion == 0) && (this._MinorVersion == 2))
                    {
                        this._MajorVersion = 2;
                        this._MinorVersion = 0;
                    }
                    int num3 = oNS.ReadByte() << 8;
                    num3 += oNS.ReadByte();
                    int num4 = oNS.ReadByte() << 8;
                    num4 += oNS.ReadByte();
                    int num5 = oNS.ReadByte() << 8;
                    num5 += oNS.ReadByte();
                    this._CipherSuites = new uint[num3 / 3];
                    for (int i = 0; i < this._CipherSuites.Length; i++)
                    {
                        this._CipherSuites[i] = (uint) (((oNS.ReadByte() << 0x10) + (oNS.ReadByte() << 8)) + oNS.ReadByte());
                    }
                    this._SessionID = new byte[num4];
                    num = oNS.Read(this._SessionID, 0, this._SessionID.Length);
                    this._Random = new byte[num5];
                    num = oNS.Read(this._Random, 0, this._Random.Length);
                    break;
                }
                case 0x16:
                {
                    this._HandshakeVersion = 3;
                    this._MajorVersion = oNS.ReadByte();
                    this._MinorVersion = oNS.ReadByte();
                    int num7 = oNS.ReadByte() << 8;
                    num7 += oNS.ReadByte();
                    if (oNS.ReadByte() != 1)
                    {
                        return false;
                    }
                    byte[] buffer = new byte[3];
                    if (oNS.Read(buffer, 0, buffer.Length) < 3)
                    {
                        return false;
                    }
                    this._MessageLen = ((buffer[0] << 0x10) + (buffer[1] << 8)) + buffer[2];
                    this._MajorVersion = oNS.ReadByte();
                    this._MinorVersion = oNS.ReadByte();
                    this._Random = new byte[0x20];
                    if (oNS.Read(this._Random, 0, 0x20) < 0x20)
                    {
                        return false;
                    }
                    int num9 = oNS.ReadByte();
                    this._SessionID = new byte[num9];
                    num = oNS.Read(this._SessionID, 0, this._SessionID.Length);
                    buffer = new byte[2];
                    if (oNS.Read(buffer, 0, buffer.Length) < 2)
                    {
                        return false;
                    }
                    int num10 = (buffer[0] << 8) + buffer[1];
                    this._CipherSuites = new uint[num10 / 2];
                    buffer = new byte[num10];
                    if (oNS.Read(buffer, 0, buffer.Length) != buffer.Length)
                    {
                        return false;
                    }
                    for (int j = 0; j < this._CipherSuites.Length; j++)
                    {
                        this._CipherSuites[j] = (uint) ((buffer[2 * j] << 8) + buffer[(2 * j) + 1]);
                    }
                    int num12 = oNS.ReadByte();
                    if (num12 < 1)
                    {
                        return false;
                    }
                    this._CompressionSuites = new byte[num12];
                    for (int k = 0; k < this._CompressionSuites.Length; k++)
                    {
                        int num14 = oNS.ReadByte();
                        if (num14 < 0)
                        {
                            return false;
                        }
                        this._CompressionSuites[k] = (byte) num14;
                    }
                    if ((this._MajorVersion < 3) || ((this._MajorVersion == 3) && (this._MinorVersion < 1)))
                    {
                        return true;
                    }
                    buffer = new byte[2];
                    if (oNS.Read(buffer, 0, buffer.Length) < 2)
                    {
                        return true;
                    }
                    int num15 = (buffer[0] << 8) + buffer[1];
                    if (num15 < 1)
                    {
                        return true;
                    }
                    buffer = new byte[num15];
                    if (oNS.Read(buffer, 0, buffer.Length) == buffer.Length)
                    {
                        this.ParseClientHelloExtensions(buffer);
                    }
                    break;
                }
            }
            return true;
        }

        private void ParseClientHelloExtension(int iExtType, byte[] arrData)
        {
            if (this._Extensions == null)
            {
                this._Extensions = new List<string>();
            }
            switch (iExtType)
            {
                case 0x3374:
                    this._Extensions.Add(string.Format("\tNextProtocolNegotiation\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 0x754f:
                    this._Extensions.Add(string.Format("\tchannel_id(GoogleDraft)\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 0xff01:
                    this._Extensions.Add(string.Format("\trenegotiation_info\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 0:
                {
                    int num3;
                    StringBuilder builder = new StringBuilder();
                    for (int i = 2; i < arrData.Length; i += 3 + num3)
                    {
                        int num2 = arrData[i];
                        num3 = (arrData[i + 1] << 8) + arrData[i + 2];
                        string str = Encoding.ASCII.GetString(arrData, i + 3, num3);
                        if (num2 == 0)
                        {
                            this._ServerNameIndicator = str;
                            builder.AppendFormat("{0}{1}", (builder.Length > 1) ? "; " : string.Empty, str);
                        }
                    }
                    this._Extensions.Add(string.Format("\tserver_name\t{0}", builder.ToString()));
                    return;
                }
                case 1:
                    this._Extensions.Add(string.Format("\tmax_fragment_length\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 2:
                    this._Extensions.Add(string.Format("\tclient_certificate_url\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 3:
                    this._Extensions.Add(string.Format("\ttrusted_ca_keys\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 4:
                    this._Extensions.Add(string.Format("\ttruncated_hmac\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 5:
                    this._Extensions.Add(string.Format("\tstatus_request\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 6:
                    this._Extensions.Add(string.Format("\tuser_mapping\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 9:
                    this._Extensions.Add(string.Format("\tcert_type\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 10:
                    this._Extensions.Add(string.Format("\telliptic_curves\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 11:
                    this._Extensions.Add(string.Format("\tec_point_formats\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 12:
                    this._Extensions.Add(string.Format("\tsrp_rfc_5054\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 13:
                    this._Extensions.Add(string.Format("\tsignature_algorithms\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 14:
                    this._Extensions.Add(string.Format("\tuse_srtp\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;

                case 0x23:
                    this._Extensions.Add(string.Format("\tSessionTicket TLS\t{0}", Utilities.ByteArrayToString(arrData)));
                    return;
            }
            this._Extensions.Add(string.Format("\t0x{0:x4}\t\t{1}", iExtType, Utilities.ByteArrayToString(arrData)));
        }

        private void ParseClientHelloExtensions(byte[] arrExtensionsData)
        {
            int num3;
            for (int i = 0; i < arrExtensionsData.Length; i += 4 + num3)
            {
                int iExtType = (arrExtensionsData[i] << 8) + arrExtensionsData[i + 1];
                num3 = (arrExtensionsData[i + 2] << 8) + arrExtensionsData[i + 3];
                byte[] dst = new byte[num3];
                Buffer.BlockCopy(arrExtensionsData, i + 4, dst, 0, dst.Length);
                this.ParseClientHelloExtension(iExtType, dst);
            }
        }

        public override string ToString()
        {
            StringBuilder builder = new StringBuilder(0x200);
            if (this._HandshakeVersion == 2)
            {
                builder.Append("A SSLv2-compatible ClientHello handshake was found. Fiddler extracted the parameters below.\n\n");
            }
            else
            {
                builder.Append("A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.\n\n");
            }
            builder.AppendFormat("Major Version: {0}\n", this._MajorVersion);
            builder.AppendFormat("Minor Version: {0}\n", this._MinorVersion);
            builder.AppendFormat("Random: {0}\n", Utilities.ByteArrayToString(this._Random));
            builder.AppendFormat("SessionID: {0}\n", Utilities.ByteArrayToString(this._SessionID));
            builder.AppendFormat("Ciphers: \n{0}\n", CipherSuitesToString(this._CipherSuites));
            builder.AppendFormat("Compression: \n{0}\n", CompressionSuitesToString(this._CompressionSuites));
            builder.AppendFormat("Extensions: \n{0}\n", ExtensionListToString(this._Extensions));
            return builder.ToString();
        }

        public string ServerNameIndicator
        {
            get
            {
                if (!string.IsNullOrEmpty(this._ServerNameIndicator))
                {
                    return this._ServerNameIndicator;
                }
                return string.Empty;
            }
        }

        public string SessionID
        {
            get
            {
                if (this._SessionID == null)
                {
                    return string.Empty;
                }
                return Utilities.ByteArrayToString(this._SessionID);
            }
        }
    }
}

